package com.example.recall31;

/**
 * @description 正则匹配，* 匹配任意多个（大于等于0）任意字符，？ 匹配零个或者一个任务字符
 * @auther lijiewei
 * @date 2022/2/9 17:15
 */
public class Pattern {

    private boolean matched = false;
    //正则表达式
    private char[] pattern;
    //正则表达式长度
    private int plen;

    public Pattern(char[] pattern, int plen) {
        this.pattern = pattern;
        this.plen = plen;
    }

    /**
     * 字符串是否完全匹配
     * @param text 文本
     * @param tlen 文本长度
     * @return
     * @author lijiewei
     * @date   2022/2/9 17:23
     */
    public boolean match(char[] text, int tlen) {
        matched = false;
        rmatch(0, 0, text, tlen);
        return matched;
    }

    /**
     * 右侧匹配
     * @param ti 文本下标
     * @param pi 匹配符下标
     * @param text 文本
     * @param tlen 文本长度
     * @return
     * @author lijiewei
     * @date   2022/2/9 17:28
     */
    private void rmatch(int ti, int pi, char[] text, int tlen) {
        //如果已经匹配了，就不要继续匹配了
        if (matched){
            return;
        }
        //正则表达式到结尾了
        if (pi == plen) {
            //完全匹配，需要文本都到结尾了
            if (ti == tlen) {
                matched = true;
            }
            return;
        }
        // * 匹配任意个字符
        if (pattern[pi] == '*') {
            //遍历后续文本
            for (int k = 0; k <= tlen-ti; k++) {
                //在文本中查找是否有字符可以对应匹配串中 * 的后一个字符
                rmatch(ti+k, pi+1, text, tlen);
            }
        } else if (pattern[pi] == '?') {
            // ？ 匹配0个或者1个字符
            // 文本当前字符或者后一个字符进行和匹配串中 ？ 的后一个字符进行匹配
            rmatch(ti, pi+1, text, tlen);
            rmatch(ti+1, pi+1, text, tlen);
        } else if (ti < tlen && pattern[pi] == text[ti]){
            //纯字符匹配
            rmatch(ti+1, pi+1, text, tlen);
        }
    }
}
